﻿#if true
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Engine;
using Engine.Attributes;

namespace Engine.Components.CompArch
{
	public class MemoryBank: MemoryBase
	{
		/// <summary>
		/// The actual storage for memory.  
        /// </summary>
		private byte[] locations;

		/// <summary>
		/// Creates a new Memory Component
		/// </summary>
		public MemoryBank() 
		{
			this.InvalidAddressFlag.Value = false;
			this.Alignment.Value = MemoryDefaults.DEFAULT_ALIGNMENT;

            this.IsWrite.Run = this.OnIsWriteSet;
            this.Address.Run = this.OnAddressSet;

			this.size = MemoryDefaults.DEFAULT_SIZE;
			this.locations = new byte[this.size];
            Reset();
		}

		// backing variable for the Size property
		private UInt32 size;

		/// <summary>
		/// Size, in bytes, of this Memory
		/// </summary>
		public override UInt32 Size
		{
			get { return this.size; }
			set
			{
				this.size = value;
				this.locations = new byte[this.size];
                Reset();
			}
		}

        /// <summary>
        /// Delegate executed when the Address InPort is set
        /// </summary>
        private void OnAddressSet()
        {
            // check address bounds
            if (Address.Value + (int)Alignment.Value - 1 > Size)
            {
                InvalidAddressFlag.Value = true;
                return;
            }
            else if (Address.Value % (int)Alignment.Value != 0) // check alignment
            {
                InvalidAddressFlag.Value = true;
                return;
            }
            else
            {
                InvalidAddressFlag.Value = false;
            }
        }

        /// <summary>
        /// Delegate executed when the IsWrite port is set
        /// </summary>
		public void OnIsWriteSet()
		{
            if (InvalidAddressFlag.Value) return;

			// calculate the position of this address in the locations array
            UInt32 loc = Address.Value;

			if (IsWrite.Value)
			{
                Writes += 1;
                for (int i = 0; i < (int)Alignment.Value; i++)
                {
                    locations[loc + i] = WritePort.Value[i];
                }
			}
			else // is a Read
			{
                Reads += 1;
                ReadPort.Value = new byte[(int)Alignment.Value];
                for (int i = 0; i < (int)Alignment.Value; i++)
                {
                    ReadPort.Value[i] = locations[loc+i];
                }
			}
		}

        /// <summary>
        /// Number of reads from this MemoryBank
        /// </summary>
        [Inspectable]
        public int Reads { get; private set; }

        /// <summary>
        /// Number of writes to this MemoryBank
        /// </summary>
        [Inspectable]
        public int Writes { get; private set; }

        public override void Reset()
        {
            Reads = 0;
            Writes = 0;
            for (int i = 0; i < locations.Length; i++)
            {
                locations[i] = 0;
            }
        }
	}
}
#endif